/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package poker.geneticAlgorithm;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Parents <x1,...,xn> and <y1,...,yn>
 * 
 * Child is:
 * a*<x> + (1-a)*<y>
 * 
 * Averaging is a = 0.5, but this yields identical children
 * 
 * 
 * @author Benjamin L. Brodie <blbrodie@gmail.com>
 */
public class WholeArithmeticCrossover implements Crossover<Individual<Double>>{

    
    /**
     * Generates a random alpha, and applies
     * alpha * <x> + (1 - a)*<y> to generate a child. Opposite for other child.
     * 
     * 
     * @param individuals the list of individuals. Must only be 2 individuals
     * @return the list of crossed individuals;
     */
    public List<Individual<Double>> cross(List<Individual<Double>> individuals) {
       return cross(individuals, Math.random());
    }
    
    
    /**
     * Applies alpha * <x> + (1 - a)*<y> to generate a child using a predefined
     * alpha value. Opposite for other child.
     * 
     * If alpha = 0.5, both children will be identical.
     * 
     * 
     * @param individuals the individuals to be crossed
     * @param alpha the preset alpha value
     * @return 
     */
    public List<Individual<Double>> cross(List<Individual<Double>> individuals, double alpha){
        
        if (alpha < 0 || alpha > 1){
            throw new IllegalArgumentException("alpha must be [0,1]");
        }
        
        if (individuals.size() > 2){
            throw new IllegalArgumentException("crossover can only operate on two individuals");
        }
        
        List<Double> parent_1 = individuals.get(0).getList();
        List<Double> parent_2 = individuals.get(1).getList();
        
        if (parent_1.size() != parent_2.size()){
            throw new IllegalArgumentException("individuals are not the same size!");
        }
        
        
        
        
        Iterator<Double> iter_1 = parent_1.iterator();
        Iterator<Double> iter_2 = parent_2.iterator();
        
        List<Double> child_1 = new ArrayList<Double>();
        List<Double> child_2 = new ArrayList<Double>();
        
        //do the math
        double weight_1;
        double weight_2;
        while (iter_1.hasNext() && iter_2.hasNext()){
            
            weight_1 = iter_1.next();
            weight_2 = iter_2.next();
            
            child_1.add(alpha*weight_1 + (1-alpha)*weight_2);
            child_2.add(alpha*weight_2 + (1-alpha)*weight_1);
        }
        
        //set up return
        List<Individual<Double>> crossed = new ArrayList<Individual<Double>>();
        crossed.add(new WeightsIndividual(child_1));
        crossed.add(new WeightsIndividual(child_2));
        return crossed;
        
        
        
        
        
        
        
    }
    
    
    
}
